package com.yyj.util.Http;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.ConnectException;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.UUID;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;

import com.yyj.constant.WebConstant;
import com.yyj.util.RspUtils;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

public class HttpClientUtil {
	private static Logger log = Logger.getLogger(HttpClientUtil.class);
	
	public static final String POSTTYPE = "post";
	public static final String GETTYPE = "get";
	
	static {
		HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier(){

	        public boolean verify(String hostname, SSLSession sslSession) {
	            if (hostname.equals("192.168.11.142")) {
	                return true;
	            }
	            return false;
	        }
	    });
	}
	
	public static String POST(String uri,Map<String, Object> temp_map) throws UnsupportedEncodingException{
		
		String result = "";
		CloseableHttpClient client = HttpClients.createDefault();
		HttpPost httppost =  new HttpPost(uri);
		
		String temp_str = parseParam_to_string(temp_map, "p");
		Map<String, Object> param = parseParam_to_map(temp_str);
		// 创建参数队列    
        List<NameValuePair> formparams = new ArrayList<NameValuePair>();  
        if(param != null){
	        Set<Entry<String, Object>>  paramSet =  param.entrySet();
	        for (Iterator<Entry<String, Object>> iterator = paramSet.iterator(); iterator.hasNext();) {
				Entry<String, Object> entry = (Entry<String, Object>) iterator .next();
				String value = entry.getValue().toString();
				String key = entry.getKey();
				formparams.add(new BasicNameValuePair(key, URLDecoder.decode(value, "utf-8") ));  
			}
        }
        UrlEncodedFormEntity uefEntity;  
        try {  
            uefEntity = new UrlEncodedFormEntity(formparams, "UTF-8");  
            httppost.setEntity(uefEntity);  
            CloseableHttpResponse response = client.execute(httppost);  
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != 200) {  
            	result = "";//JSONObject.toJSONString(JSONResult.fail("请求返回失败！", statusCode)); 
            }else{ 
	            try {  
	                HttpEntity entity = response.getEntity();  
	                if (entity != null) {  
	                	result= EntityUtils.toString(entity, "UTF-8"); 
	                }  
	            } finally {  
	                response.close();  
	            }  
            }
        } catch (Exception e) {  
        	log.error(e.getMessage(), e);
        	result = "";//JSONObject.toJSONString(JSONResult.fail("服务器访问失败！", 500)); 
        } finally {  
            // 关闭连接,释放资源    
            try {  
            	client.close();  
            } catch (IOException e) {  
            	log.error(e.getMessage(), e); 
            }  
        } 
		return result;
	}
	
	public static String GET(String uri,Map<String,Object> param) throws UnsupportedEncodingException{
		
		String result = "";
		String uri_str = creatGETUrl(uri, param) ;
		
		CloseableHttpClient httpclient = HttpClients.createDefault();  
        try {  
            // 创建httpget.    
            HttpGet httpget = new HttpGet(uri_str);  
            // 执行get请求.    
            CloseableHttpResponse response = httpclient.execute(httpget); 
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != 200) {  
            	result = "";//JSONObject.toJSONString(JSONResult.fail("请求返回失败！", statusCode)); 
            }else{ 
	            try {  
	                // 获取响应实体    
	                HttpEntity entity = response.getEntity();  
	                if (entity != null) {  
	                    // 打印响应内容长度    
	                    result = EntityUtils.toString(entity);  
	                }  
	            } finally {  
	                response.close();  
	            }  
            }
        } catch (Exception e) {  
        	log.error(e.getMessage(), e);
        	result = "";//JSONObject.toJSONString(JSONResult.fail("服务器访问失败！", 500)); 
        } finally {  
            // 关闭连接,释放资源    
            try {
            	httpclient.close();  
            } catch (IOException e) {  
            	log.error(e.getMessage(), e); 
            }  
        } 
        
        return result;
	}
	
	/**
	 * 根据url查询字符串("key1=value1&key2=value2")构造map
	 * @param param
	 * @return
	 * @throws UnsupportedEncodingException 
	 */
	public static Map<String ,Object> parseParam_to_map(String param) throws UnsupportedEncodingException{
		Map<String ,Object> result = null;
		int indexof = param.lastIndexOf("&");
		if(param != null && !"".equals(param)){
			try{
				result = new HashMap<String,Object>();
				if(indexof == -1){
					makeMap(param, result);
				}else{
					String[] entry_str = param.split("&");
					for(String ent:entry_str){
						makeMap(ent,result);
					}
				}
			}catch(ArrayIndexOutOfBoundsException e){
				result = null;
			}
		}
		return result;
	}
	
	/**
	 * 将map类型的对象 装换成url参数格式字符串
	 * @param urlParam
	 * @return
	 * @throws UnsupportedEncodingException 
	 */
	public static String parseParam_to_string(Map<String, Object> urlParam,String jsontype) throws UnsupportedEncodingException{
		String param_str = "";
		if(urlParam != null){
			param_str += jsontype+"=";
			String json_ = "";
			Set<Entry<String, Object>> entrys = urlParam.entrySet();
			Iterator<Entry<String, Object>> entrys_interator = entrys.iterator();
			while(entrys_interator.hasNext()){
				Entry<String, Object> entry = entrys_interator.next();
				
				String key = entry.getKey();
				String value = "";
				
				Object val = entry.getValue();
				if(val == null){
					value = "";
				}else{
					if(val instanceof String){
						value = val.toString();
					}else{
						value = val.toString();
					}
				}
				
				json_ += "\""+ key + "\":\"" + value + "\",";
			}
			int lastindex = json_.lastIndexOf(",");
			json_ = json_.substring(0, lastindex);
			param_str += URLEncoder.encode("{"+json_+"}","UTF-8");
		}
		return param_str ;
	}
	
	/**
	 * 根据约定好的字符串("key=value")构造map
	 * @param entry_str
	 * @param toMaked ，要构造的map的引用
	 */
	private static void makeMap(String entry_str,Map<String ,Object> toMaked){
		String[] entry = entry_str.split("="); 
		toMaked.put(entry[0], entry[1]);
		entry = null;
	}
	
	public static String creatGETUrl(String uri,Map<String,Object> param) throws UnsupportedEncodingException{
		if(param == null){
			return uri;
		}else{
			int index = -1;
			String autr = "";//锚点
			boolean isQuery = false;//原链接是否已有参数
			String fallBack_temp = uri;
			
			String result_str = parseParam_to_string(param, "p");
			
			if((index = fallBack_temp.indexOf("#")) > 0){
				autr = fallBack_temp.substring(index);
				fallBack_temp = fallBack_temp.substring(0, index);
			}
			
			if(fallBack_temp.indexOf("?") > 0){
				isQuery = true;
			}
			
			StringBuffer fb_temp = new StringBuffer(fallBack_temp);
			String randomuuid = UUID.randomUUID().toString().replaceAll("-", "");
			if(isQuery){
				fb_temp.append("&"+result_str+"&vi="+randomuuid+autr);
			}else{
				fb_temp.append("?"+result_str+"&vi="+randomuuid+autr);
			}
			return fb_temp.toString();
		}
	}
	
	/** POST请求的RAW参数传递
	 * 
	 * 	uri:请求地址
	 * 	param：请求参数
	 * 	jsonKey：是否需要加data={}
	 * 	contentType：请求头类型
	 * 
	 * */
	public static String postByRaw(String uri,Map<String, Object> param , String jsonKey, String contentType) throws UnsupportedEncodingException{
		
		String result = "";
		CloseableHttpClient client = HttpClients.createDefault();
		
		String requestParams = JSON.toJSONString(param);
		if(jsonKey != null){
			requestParams = jsonKey.concat("=").concat(requestParams);
		}
		
        try {  
        	RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(WebConstant.HTTP_SOCKET_TIMEOUT).setConnectTimeout(WebConstant.HTTP_CONNECT_TIMEOUT).build();
    		HttpPost httppost =  new HttpPost(uri);
    		httppost.setHeader("content-type", contentType);
    		httppost.setConfig(requestConfig);
            httppost.setEntity(new StringEntity(requestParams));  
            CloseableHttpResponse response = client.execute(httppost);  
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != WebConstant.HTTP_CODE_200) {  
            	result = JSONObject.toJSONString(RspUtils.error("", "请求返回失败！", statusCode));
            }else{ 
	            try {  
	                HttpEntity entity = response.getEntity();  
	                if (entity != null) {  
	                	result= EntityUtils.toString(entity, "UTF-8"); 
	                }  
	            } finally {  
	                response.close();  
	            }  
            }
        } catch (Exception e) {  
        	log.error(e.getMessage(), e);
        	result = JSONObject.toJSONString(RspUtils.error("", "服务器访问失败！", WebConstant.HTTP_CODE_500));
        } finally {  
            // 关闭连接,释放资源    
            try {  
            	client.close();  
            } catch (IOException e) {  
            	log.error(e.getMessage(), e); 
            }  
        } 
		return result;
	}
	
	/**
	 * 发起https请求并获取结果
	 * 
	 * @param requestUrl
	 *            请求地址
	 * @param requestMethod
	 *            请求方式（GET、POST）
	 * @param outputStr
	 *            提交的数据
	 * @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
	 */
	public static String httpsRequest(String requestUrl,
			String requestMethod, String outputStr) {
		String result = "";
		StringBuffer buffer = new StringBuffer();
		try {
			// 创建SSLContext对象，并使用我们指定的信任管理器初始化
			TrustManager[] tm = { new MyX509TrustManager() };
			SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
			sslContext.init(null, tm, new java.security.SecureRandom());
			// 从上述SSLContext对象中得到SSLSocketFactory对象
			SSLSocketFactory ssf = sslContext.getSocketFactory();

			URL url = new URL(requestUrl);
			HttpsURLConnection httpUrlConn = (HttpsURLConnection) url
					.openConnection();
			httpUrlConn.setSSLSocketFactory(ssf);

			httpUrlConn.setDoOutput(true);
			httpUrlConn.setDoInput(true);
			httpUrlConn.setUseCaches(false);
			// 设置请求方式（GET/POST）
			httpUrlConn.setRequestMethod(requestMethod);

			if ("GET".equalsIgnoreCase(requestMethod))
				httpUrlConn.connect();
			// 当有数据需要提交时
			if (null != outputStr) {
				OutputStream outputStream = httpUrlConn.getOutputStream();
				// 注意编码格式，防止中文乱码
				outputStream.write(outputStr.getBytes("UTF-8"));
				outputStream.close();
			}

			// 将返回的输入流转换成字符串
			InputStream inputStream = httpUrlConn.getInputStream();
			InputStreamReader inputStreamReader = new InputStreamReader(
					inputStream, "utf-8");
			BufferedReader bufferedReader = new BufferedReader(
					inputStreamReader);

			String str = null;
			while ((str = bufferedReader.readLine()) != null) {
				buffer.append(str);
			}
			bufferedReader.close();
			inputStreamReader.close();
			// 释放资源
			inputStream.close();
			inputStream = null;
			httpUrlConn.disconnect();
			
			result = buffer.toString();
		} catch (ConnectException ce) {
			log.error("Weixin server connection timed out.");
		} catch (Exception e) {
			e.printStackTrace();
			log.error("https request error:{" + e + "}");
		}
		return result;
	}
	
	public static void main(String[] args) {
		System.out.println(HttpClientUtil.httpsRequest("https://wp-backend.100bei.com/hpmewp/customServiceController/getListByIdentity?identity=1&gid=gh_33b0fa019081", "GET", null));
	}
}
